/********************************************************************
 *@brief Define parameters and functions
 *@author wcf
 *@date 2025-01-11
********************************************************************/

#ifndef __CS_METHOD_H__
#define __CS_METHOD_H__

#include "cscoreglobal.h"

CS_NAMESPACE_BEGIN

//Argument
class CSCORE_EXPORT csGenericArgument
{
public:
    inline csGenericArgument(const char *name = nullptr, const void *data = nullptr)
        : m_data(data), m_name(name) {}
    bool isValid() const { return m_data != nullptr && m_name != nullptr; }
    inline void* data() const { return const_cast<void*>(m_data); }
    inline const char* name() const { return m_name; }
    template <typename T>
    inline T* value() const { return reinterpret_cast<T(*)>(data()); }
private:
    const void* m_data = nullptr;
    const char* m_name = nullptr;
};

class CSCORE_EXPORT csGenericReturnArgument: public csGenericArgument
{
public:
    inline csGenericReturnArgument(const char* name = nullptr, void* data = nullptr)
        : csGenericArgument(name, data)
        {}
};

template <class T>
class csArgument: public csGenericArgument
{
public:
    inline csArgument(const char* name, const T& data)
        : csGenericArgument(name, static_cast<const void*>(&data))
        {}
};

template <class T>
class csArgument<T&>: public csGenericArgument
{
public:
    inline csArgument(const char* name, T& data)
        : csGenericArgument(name, static_cast<const void*>(&data))
        {}
};

template <typename T>
class csReturnArgument: public csGenericReturnArgument
{
public:
    inline csReturnArgument(const char* name, T& data)
        : csGenericReturnArgument(name, static_cast<void*>(&data))
        {}
};

#define CS_ARG(type, data) csArgument<type>(#type, data)
#define CS_RETURN_ARG(type, data) csReturnArgument<type>(#type, data)

//csGenericMethod
class CSCORE_EXPORT csGenericMethod
{
public:
    inline csGenericMethod(const char* name, const void* object)
        : m_name(name), m_object(object) {}
    virtual ~csGenericMethod() = default;
    inline const char* name() const { return m_name; }
    inline void* object() const { return const_cast<void *>(m_object); }
    virtual bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) = 0;
private:
    const char* m_name;
    const void* m_object;
};

//csMethod
template
<
    typename ObjectType,
    typename MethodType
>
class csMethod : public csGenericMethod
{
public:
    inline csMethod(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(ret);
        CS_UNUSED(arg1);
        CS_UNUSED(arg2);
        CS_UNUSED(arg3);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        (obj->*m_method)();
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_METHOD(\
    ObjectType,\
    Method,\
    ConstType)\
    {\
        std::string signature = #Method + std::string("()");\
        using MethodType = void (ObjectType::*)() ConstType;\
        registerMethod(signature, new csMethod<ObjectType, MethodType>(&ObjectType::Method, #Method, this));\
    }

//csArgument1Method
template
<
    typename ObjectType,
    typename MethodType,
    typename Argument1Type
>
class csArgument1Method : public csGenericMethod
{
public:
    inline csArgument1Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(ret);
        CS_UNUSED(arg2);
        CS_UNUSED(arg3);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!arg1.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        (obj->*m_method)(*arg1.value<Arg1Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_ARG1METHOD(\
    ObjectType,\
    Method,\
    Arg1Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + std::string(")");\
        using MethodType = void (ObjectType::*)(Arg1Type) ConstType;\
        registerMethod(signature, new csArgument1Method<ObjectType, MethodType, Arg1Type>(&ObjectType::Method, #Method, this));\
    }

//csArgument2Method
template
<
    typename ObjectType,
    typename MethodType,
    typename Argument1Type,
    typename Argument2Type
>
class csArgument2Method : public csGenericMethod
{
public:
    inline csArgument2Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(ret);
        CS_UNUSED(arg3);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!arg1.isValid() || !arg2.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        (obj->*m_method)(
                    *arg1.value<Arg1Type>(),
                    *arg2.value<Arg2Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_ARG2METHOD(\
    ObjectType,\
    Method,\
    Arg1Type,\
    Arg2Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + std::string(")");\
        using MethodType = void (ObjectType::*)(Arg1Type,Arg2Type) ConstType;\
        registerMethod(signature, new csArgument2Method<ObjectType, MethodType, Arg1Type, Arg2Type>(&ObjectType::Method, #Method, this));\
    }

//csArgument3Method
template
<
    typename ObjectType,
    typename MethodType,
    typename Argument1Type,
    typename Argument2Type,
    typename Argument3Type
>
class csArgument3Method : public csGenericMethod
{
public:
    inline csArgument3Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(ret);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!arg1.isValid() || !arg2.isValid() || !arg3.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        using Arg3Type = typename std::remove_reference<Argument3Type>::type;
        (obj->*m_method)(
                    *arg1.value<Arg1Type>(),
                    *arg2.value<Arg2Type>(),
                    *arg3.value<Arg3Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_ARG3METHOD(\
    ObjectType,\
    Method,\
    Arg1Type,\
    Arg2Type,\
    Arg3Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + "," + #Arg3Type+ std::string(")");\
        using MethodType = void (ObjectType::*)(Arg1Type,Arg2Type,Arg3Type) ConstType;\
        registerMethod(signature, new csArgument3Method<ObjectType, MethodType, Arg1Type, Arg2Type, Arg3Type>(&ObjectType::Method, #Method, this));\
    }

//csArgument4Method
template
<
    typename ObjectType,
    typename MethodType,
    typename Argument1Type,
    typename Argument2Type,
    typename Argument3Type,
    typename Argument4Type
>
class csArgument4Method : public csGenericMethod
{
public:
    inline csArgument4Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(ret);
        CS_UNUSED(arg5);
        if (!arg1.isValid() || !arg2.isValid() || !arg3.isValid() || !arg4.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        using Arg3Type = typename std::remove_reference<Argument3Type>::type;
        using Arg4Type = typename std::remove_reference<Argument4Type>::type;
        (obj->*m_method)(
                    *arg1.value<Arg1Type>(),
                    *arg2.value<Arg2Type>(),
                    *arg3.value<Arg3Type>(),
                    *arg4.value<Arg4Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_ARG4METHOD(\
    ObjectType,\
    Method,\
    Arg1Type,\
    Arg2Type,\
    Arg3Type,\
    Arg4Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + "," + #Arg3Type + "," + #Arg4Type + std::string(")");\
        using MethodType = void (ObjectType::*)(Arg1Type,Arg2Type,Arg3Type, Arg4Type) ConstType;\
        registerMethod(signature, new csArgument4Method<ObjectType, MethodType, Arg1Type, Arg2Type, Arg3Type, Arg4Type>(&ObjectType::Method, #Method, this));\
    }

//csArgument5Method
template
<
    typename ObjectType,
    typename MethodType,
    typename Argument1Type,
    typename Argument2Type,
    typename Argument3Type,
    typename Argument4Type,
    typename Argument5Type
>
class csArgument5Method : public csGenericMethod
{
public:
    inline csArgument5Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(ret);
        if (!arg1.isValid() || !arg2.isValid() || !arg3.isValid() || !arg4.isValid() || !arg5.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        using Arg3Type = typename std::remove_reference<Argument3Type>::type;
        using Arg4Type = typename std::remove_reference<Argument4Type>::type;
        using Arg5Type = typename std::remove_reference<Argument5Type>::type;
        (obj->*m_method)(
                    *arg1.value<Arg1Type>(),
                    *arg2.value<Arg2Type>(),
                    *arg3.value<Arg3Type>(),
                    *arg4.value<Arg4Type>(),
                    *arg5.value<Arg5Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_ARG5METHOD(\
    ObjectType,\
    Method,\
    Arg1Type,\
    Arg2Type,\
    Arg3Type,\
    Arg4Type,\
    Arg5Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + "," + #Arg3Type + "," + #Arg4Type + "," + #Arg5Type + std::string(")");\
        using MethodType = void (ObjectType::*)(Arg1Type,Arg2Type,Arg3Type, Arg4Type, Arg5Type) ConstType;\
        registerMethod(signature, new csArgument5Method<ObjectType, MethodType, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type>(&ObjectType::Method, #Method, this));\
    }

//XReturnMethod
template
<
    typename ObjectType,
    typename MethodType,
    typename ReturnType
>
class XReturnMethod : public csGenericMethod
{
public:
    inline XReturnMethod(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(arg1);
        CS_UNUSED(arg2);
        CS_UNUSED(arg3);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!ret.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using RetType = typename std::remove_const<std::remove_reference<ReturnType>::type>::type;
        *(reinterpret_cast<RetType*>(ret.data())) = (obj->*m_method)();
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_RETURN_METHOD(\
    ObjectType,\
    Method,\
    ReturnType,\
    ConstType)\
    {\
        std::string signature = #Method + std::string("()");\
        using MethodType = ReturnType (ObjectType::*)() ConstType;\
        registerMethod(signature, new XReturnMethod<ObjectType, MethodType, ReturnType>(&ObjectType::Method, #Method, this));\
    }

//csReturnArgument1Method
template
<
    typename ObjectType,
    typename MethodType,
    typename ReturnType,
    typename Argument1Type
>
class csReturnArgument1Method : public csGenericMethod
{
public:
    inline csReturnArgument1Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(arg2);
        CS_UNUSED(arg3);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!ret.isValid() || !arg1.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using RetType = typename std::remove_const<std::remove_reference<ReturnType>::type>::type;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        *(reinterpret_cast<RetType*>(ret.data())) =
                (obj->*m_method)(*arg1.value<Arg1Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_RETURN_ARG1METHOD(\
    ObjectType,\
    Method,\
    ReturnType,\
    Arg1Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + std::string(")");\
        using MethodType = ReturnType (ObjectType::*)(Arg1Type) ConstType;\
        registerMethod(signature, new csReturnArgument1Method<ObjectType, MethodType, ReturnType, Arg1Type>(&ObjectType::Method, #Method, this));\
    }

//csReturnArgument2Method
template
<
    typename ObjectType,
    typename MethodType,
    typename ReturnType,
    typename Argument1Type,
    typename Argument2Type
>
class csReturnArgument2Method : public csGenericMethod
{
public:
    inline csReturnArgument2Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(arg3);
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!ret.isValid() || !arg1.isValid() || !arg2.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using RetType = typename std::remove_const<std::remove_reference<ReturnType>::type>::type;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        *(reinterpret_cast<RetType*>(ret.data())) =
                (obj->*m_method)(*arg1.value<Arg1Type>(),
                                 *arg2.value<Arg2Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_RETURN_ARG2METHOD(\
    ObjectType,\
    Method,\
    ReturnType,\
    Arg1Type,\
    Arg2Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + std::string(")");\
        using MethodType = ReturnType (ObjectType::*)(Arg1Type, Arg2Type) ConstType;\
        registerMethod(signature, new csReturnArgument2Method<ObjectType, MethodType, ReturnType, Arg1Type, Arg2Type>(&ObjectType::Method, #Method, this));\
    }

//csReturnArgument3Method
template
<
    typename ObjectType,
    typename MethodType,
    typename ReturnType,
    typename Argument1Type,
    typename Argument2Type,
    typename Argument3Type
>
class csReturnArgument3Method : public csGenericMethod
{
public:
    inline csReturnArgument3Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(arg4);
        CS_UNUSED(arg5);
        if (!ret.isValid() || !arg1.isValid() || !arg2.isValid() || !arg3.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using RetType = typename std::remove_const<std::remove_reference<ReturnType>::type>::type;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        using Arg3Type = typename std::remove_reference<Argument3Type>::type;
        *(reinterpret_cast<RetType*>(ret.data())) =
                (obj->*m_method)(*arg1.value<Arg1Type>(),
                                 *arg2.value<Arg2Type>(),
                                 *arg3.value<Arg3Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_RETURN_ARG3METHOD(\
    ObjectType,\
    Method,\
    ReturnType,\
    Arg1Type,\
    Arg2Type,\
    Arg3Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + "," + #Arg3Type + std::string(")");\
        using MethodType = ReturnType (ObjectType::*)(Arg1Type, Arg2Type, Arg3Type) ConstType;\
        registerMethod(signature, new csReturnArgument3Method<ObjectType, MethodType, ReturnType, Arg1Type, Arg2Type, Arg3Type>(&ObjectType::Method, #Method, this));\
    }

//csReturnArgument4Method
template
<
    typename ObjectType,
    typename MethodType,
    typename ReturnType,
    typename Argument1Type,
    typename Argument2Type,
    typename Argument3Type,
    typename Argument4Type
>
class csReturnArgument4Method : public csGenericMethod
{
public:
    inline csReturnArgument4Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        CS_UNUSED(arg5);
        if (!ret.isValid() || !arg1.isValid() || !arg2.isValid() || !arg3.isValid() || !arg4.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using RetType = typename std::remove_const<std::remove_reference<ReturnType>::type>::type;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        using Arg3Type = typename std::remove_reference<Argument3Type>::type;
        using Arg4Type = typename std::remove_reference<Argument4Type>::type;
        *(reinterpret_cast<RetType*>(ret.data())) =
                (obj->*m_method)(*arg1.value<Arg1Type>(),
                                 *arg2.value<Arg2Type>(),
                                 *arg3.value<Arg3Type>(),
                                 *arg4.value<Arg4Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_RETURN_ARG4METHOD(\
    ObjectType,\
    Method,\
    ReturnType,\
    Arg1Type,\
    Arg2Type,\
    Arg3Type,\
    Arg4Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + "," + #Arg3Type + "," + #Arg4Type + std::string(")");\
        using MethodType = ReturnType (ObjectType::*)(Arg1Type, Arg2Type, Arg3Type, Arg4Type) ConstType;\
        registerMethod(signature, new csReturnArgument4Method<ObjectType, MethodType, ReturnType, Arg1Type, Arg2Type, Arg3Type, Arg4Type>(&ObjectType::Method, #Method, this));\
    }

//csReturnArgument5Method
template
<
    typename ObjectType,
    typename MethodType,
    typename ReturnType,
    typename Argument1Type,
    typename Argument2Type,
    typename Argument3Type,
    typename Argument4Type,
    typename Argument5Type
>
class csReturnArgument5Method : public csGenericMethod
{
public:
    inline csReturnArgument5Method(const MethodType& method, const char* name, const ObjectType* object)
        : csGenericMethod(name, object), m_method(method) {}
    bool invoke(
            csGenericReturnArgument ret,
            csGenericArgument arg1,
            csGenericArgument arg2,
            csGenericArgument arg3,
            csGenericArgument arg4,
            csGenericArgument arg5) override
    {
        if (!ret.isValid() || !arg1.isValid() || !arg2.isValid() || !arg3.isValid() || !arg4.isValid() || !arg5.isValid())
            return false;
        if (!m_method)
            return false;
        ObjectType* obj = reinterpret_cast<ObjectType*>(object());
        if (!obj)
            return false;
        using RetType = typename std::remove_const<std::remove_reference<ReturnType>::type>::type;
        using Arg1Type = typename std::remove_reference<Argument1Type>::type;
        using Arg2Type = typename std::remove_reference<Argument2Type>::type;
        using Arg3Type = typename std::remove_reference<Argument3Type>::type;
        using Arg4Type = typename std::remove_reference<Argument4Type>::type;
        using Arg5Type = typename std::remove_reference<Argument5Type>::type;
        *(reinterpret_cast<RetType*>(ret.data())) =
                (obj->*m_method)(*arg1.value<Arg1Type>(),
                                 *arg2.value<Arg2Type>(),
                                 *arg3.value<Arg3Type>(),
                                 *arg4.value<Arg4Type>(),
                                 *arg5.value<Arg5Type>());
        return true;
    }
private:
    MethodType m_method;
};

#define CS_REG_RETURN_ARG5METHOD(\
    ObjectType,\
    Method,\
    ReturnType,\
    Arg1Type,\
    Arg2Type,\
    Arg3Type,\
    Arg4Type,\
    Arg5Type,\
    ConstType)\
    {\
        std::string signature = #Method;\
        signature += std::string("(") + #Arg1Type + "," + #Arg2Type + "," + #Arg3Type + "," + #Arg4Type + "," + #Arg5Type + std::string(")");\
        using MethodType = ReturnType (ObjectType::*)(Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type) ConstType;\
        registerMethod(signature, new csReturnArgument5Method<ObjectType, MethodType, ReturnType, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type>(&ObjectType::Method, #Method, this));\
    }

CS_NAMESPACE_END

#endif // !__CS_METHOD_H__
